package it.webrules.deploymanager.core.dy.deploy.tomcat;

import it.webrules.deploymanager.core.dy.deploy.DeployException;
import it.webrules.deploymanager.core.utils.BasicAuth;
import it.webrules.deploymanager.core.utils.FileUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TomcatManager {

	private static final int DEPLOY_TIMEOUT = 180000;
	private static final int HTTP_STATUS_OK = 200;
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	private final URI uri;
	private final String servername;
	private final String username;
	private final String password;

	public TomcatManager(String version, String servername, String managerurl, String username, String password) throws URISyntaxException {

		if (managerurl.endsWith("html"))
			managerurl = managerurl.substring(0, managerurl.lastIndexOf("html"));

		if (!managerurl.endsWith("/"))
			managerurl = managerurl + "/";

		if (version.startsWith("7"))
			managerurl = managerurl + "text/";

		this.uri = new URI(managerurl);
		this.servername = servername;
		this.username = username;
		this.password = password;
	}

	public int isAvailability(StringBuilder errors) {

		int error = 0;

		try {

			URI uriDeploy = uri.resolve("status");
			HttpURLConnection connection = (HttpURLConnection) uriDeploy.toURL().openConnection();
			BasicAuth.setBasicAuth(connection, username, password);
			connection.setAllowUserInteraction(false);
			connection.setRequestMethod("GET");
			connection.connect();

			if (connection.getResponseCode() != HTTP_STATUS_OK) {
				error++;
				errors.append("Can't connect to server via manager (" + servername + ") HTTP Status " + connection.getResponseCode());
			}

			connection.disconnect();

		} catch (Exception e) {
			error++;
			errors.append("Can't connect to server via manager (" + servername + "):" + e.getMessage());
		}

		return error;

	}

	public boolean isPortAvailable() {

		StringBuilder errors = new StringBuilder();
		isAvailability(errors);

		if (errors.toString().trim().length() == 0) {
			logger.trace("Port Avalilable.");
			return true;
		}

		logger.trace("Port NOT Avalilable.");
		return false;

	}

	public void deploy(String contextname, InputStream artifact) throws DeployException, IOException {

		logger.info("Deploy context {}...", contextname);

		URI uriDeploy = uri.resolve("deploy?update=true&path=%2F" + contextname);
		HttpURLConnection connection = (HttpURLConnection) uriDeploy.toURL().openConnection();
		BasicAuth.setBasicAuth(connection, username, password);
		connection.setAllowUserInteraction(false);
		connection.setDoInput(true);
		connection.setUseCaches(false);
		connection.setDoOutput(true);
		connection.setConnectTimeout(DEPLOY_TIMEOUT);
		connection.setRequestMethod("PUT");
		connection.setRequestProperty("Content-Type", "application/octet-stream");
		connection.connect();

		OutputStream outputStream = connection.getOutputStream();
		FileUtils.inputStreamToOutputStream(artifact, outputStream);
		connection.getOutputStream().close();

		String response = FileUtils.convertStreamToString(connection.getInputStream());

		connection.disconnect();

		if (!response.startsWith("OK -"))
			throw new DeployException("Error deploying application on " + servername + ". Response: " + response);

		logger.info("Upload ended...");

	}

	public void undeploy(String contextname) throws IOException, DeployException {

		logger.info("Undeploy context {}...", contextname);

		URI uriUndeploy = uri.resolve("undeploy?path=%2F" + contextname);

		HttpURLConnection connection = (HttpURLConnection) uriUndeploy.toURL().openConnection();
		BasicAuth.setBasicAuth(connection, username, password);

		String response = FileUtils.convertStreamToString((InputStream) connection.getContent());

		connection.disconnect();

		if (!response.startsWith("OK -"))
			throw new DeployException("Error undeploying application on " + servername + ". Response: " + response);

	}
}
